1   /*
2    * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package sun.security.provider;
27  
28  import java.io.*;
29  import java.lang.RuntimePermission;
30  import java.lang.reflect.*;
31  import java.lang.ref.*;
32  import java.net.MalformedURLException;
33  import java.net.URL;
34  import java.net.URI;
35  import java.util.*;
36  import java.util.Enumeration;
37  import java.util.Hashtable;
38  import java.util.List;
39  import java.util.StringTokenizer;
40  import java.util.PropertyPermission;
41  import java.util.ArrayList;
42  import java.util.ListIterator;
43  import java.util.WeakHashMap;
44  import java.text.MessageFormat;
45  import com.sun.security.auth.PrincipalComparator;
46  import java.security.*;
47  import java.security.cert.Certificate;
48  import java.security.cert.X509Certificate;
49  import javax.security.auth.PrivateCredentialPermission;
50  import javax.security.auth.Subject;
51  import javax.security.auth.x500.X500Principal;
52  import java.io.FilePermission;
53  import java.net.SocketPermission;
54  import java.net.NetPermission;
55  import java.util.PropertyPermission;
56  import java.util.concurrent.atomic.AtomicReference;
57  /*
58  import javax.security.auth.AuthPermission;
59  import javax.security.auth.kerberos.ServicePermission;
60  import javax.security.auth.kerberos.DelegationPermission;
61  import java.io.SerializablePermission;
62  import java.util.logging.LoggingPermission;
63  import java.sql.SQLPermission;
64  import java.lang.reflect.ReflectPermission;
65  import javax.sound.sampled.AudioPermission;
66  import javax.net.ssl.SSLPermission;
67  */
68  import sun.misc.JavaSecurityProtectionDomainAccess;
69  import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
70  import sun.misc.SharedSecrets;
71  import sun.security.util.Password;
72  import sun.security.util.PolicyUtil;
73  import sun.security.util.PropertyExpander;
74  import sun.security.util.Debug;
75  import sun.security.util.ResourcesMgr;
76  import sun.security.util.SecurityConstants;
77  import sun.net.www.ParseUtil;
78  
79  /**
80   * This class represents a default implementation for
81   * <code>java.security.Policy</code>.
82   *
83   * Note:
84   * For backward compatibility with JAAS 1.0 it loads
85   * both java.auth.policy and java.policy. However it
86   * is recommended that java.auth.policy be not used
87   * and the java.policy contain all grant entries including
88   * that contain principal-based entries.
89   *
90   *
91   * <p> This object stores the policy for entire Java runtime,
92   * and is the amalgamation of multiple static policy
93   * configurations that resides in files.
94   * The algorithm for locating the policy file(s) and reading their
95   * information into this <code>Policy</code> object is:
96   *
97   * <ol>
98   * <li>
99   *   Loop through the <code>java.security.Security</code> properties,
100  *   <i>policy.url.1</i>, <i>policy.url.2</i>, ...,
101  *   <i>policy.url.X</i>" and
102  *   <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,
103  *   <i>auth.policy.url.X</i>".  These properties are set
104  *   in the Java security properties file, which is located in the file named
105  *   &lt;JAVA_HOME&gt;/lib/security/java.security.
106  *   &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
107  *   and specifies the directory where the JRE is installed.
108  *   Each property value specifies a <code>URL</code> pointing to a
109  *   policy file to be loaded.  Read in and load each policy.
110  *
111  *   <i>auth.policy.url</i> is supported only for backward compatibility.
112  *
113  * <li>
114  *   The <code>java.lang.System</code> property <i>java.security.policy</i>
115  *   may also be set to a <code>URL</code> pointing to another policy file
116  *   (which is the case when a user uses the -D switch at runtime).
117  *   If this property is defined, and its use is allowed by the
118  *   security property file (the Security property,
119  *   <i>policy.allowSystemProperty</i> is set to <i>true</i>),
120  *   also load that policy.
121  *
122  * <li>
123  *   The <code>java.lang.System</code> property
124  *   <i>java.security.auth.policy</i> may also be set to a
125  *   <code>URL</code> pointing to another policy file
126  *   (which is the case when a user uses the -D switch at runtime).
127  *   If this property is defined, and its use is allowed by the
128  *   security property file (the Security property,
129  *   <i>policy.allowSystemProperty</i> is set to <i>true</i>),
130  *   also load that policy.
131  *
132  *   <i>java.security.auth.policy</i> is supported only for backward
133  *   compatibility.
134  *
135  *   If the  <i>java.security.policy</i> or
136  *   <i>java.security.auth.policy</i> property is defined using
137  *   "==" (rather than "="), then ignore all other specified
138  *   policies and only load this policy.
139  * </ol>
140  *
141  * Each policy file consists of one or more grant entries, each of
142  * which consists of a number of permission entries.
143  *
144  * <pre>
145  *   grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",
146  *         principal <b>principalClass</b> "<b>principalName</b>",
147  *         principal <b>principalClass</b> "<b>principalName</b>",
148  *         ... {
149  *
150  *     permission <b>Type</b> "<b>name</b> "<b>action</b>",
151  *         signedBy "<b>alias</b>";
152  *     permission <b>Type</b> "<b>name</b> "<b>action</b>",
153  *         signedBy "<b>alias</b>";
154  *     ....
155  *   };
156  * </pre>
157  *
158  * All non-bold items above must appear as is (although case
159  * doesn't matter and some are optional, as noted below).
160  * principal entries are optional and need not be present.
161  * Italicized items represent variable values.
162  *
163  * <p> A grant entry must begin with the word <code>grant</code>.
164  * The <code>signedBy</code>,<code>codeBase</code> and <code>principal</code>
165  * name/value pairs are optional.
166  * If they are not present, then any signer (including unsigned code)
167  * will match, and any codeBase will match.
168  * Note that the <i>principalClass</i>
169  * may be set to the wildcard value, *, which allows it to match
170  * any <code>Principal</code> class.  In addition, the <i>principalName</i>
171  * may also be set to the wildcard value, *, allowing it to match
172  * any <code>Principal</code> name.  When setting the <i>principalName</i>
173  * to the *, do not surround the * with quotes.
174  *
175  * <p> A permission entry must begin with the word <code>permission</code>.
176  * The word <code><i>Type</i></code> in the template above is
177  * a specific permission type, such as <code>java.io.FilePermission</code>
178  * or <code>java.lang.RuntimePermission</code>.
179  *
180  * <p> The "<i>action</i>" is required for
181  * many permission types, such as <code>java.io.FilePermission</code>
182  * (where it specifies what type of file access that is permitted).
183  * It is not required for categories such as
184  * <code>java.lang.RuntimePermission</code>
185  * where it is not necessary - you either have the
186  * permission specified by the <code>"<i>name</i>"</code>
187  * value following the type name or you don't.
188  *
189  * <p> The <code>signedBy</code> name/value pair for a permission entry
190  * is optional. If present, it indicates a signed permission. That is,
191  * the permission class itself must be signed by the given alias in
192  * order for it to be granted. For example,
193  * suppose you have the following grant entry:
194  *
195  * <pre>
196  *   grant principal foo.com.Principal "Duke" {
197  *     permission Foo "foobar", signedBy "FooSoft";
198  *   }
199  * </pre>
200  *
201  * <p> Then this permission of type <i>Foo</i> is granted if the
202  * <code>Foo.class</code> permission has been signed by the
203  * "FooSoft" alias, or if XXX <code>Foo.class</code> is a
204  * system class (i.e., is found on the CLASSPATH).
205  *
206  *
207  * <p> Items that appear in an entry must appear in the specified order
208  * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
209  * "<i>action</i>"). An entry is terminated with a semicolon.
210  *
211  * <p> Case is unimportant for the identifiers (<code>permission</code>,
212  * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
213  * significant for the <i>Type</i>
214  * or for any string that is passed in as a value. <p>
215  *
216  * <p> An example of two entries in a policy configuration file is
217  * <pre>
218  *   // if the code is comes from "foo.com" and is running as "Duke",
219  *   // grant it read/write to all files in /tmp.
220  *
221  *   grant codeBase "foo.com", principal foo.com.Principal "Duke" {
222  *              permission java.io.FilePermission "/tmp/*", "read,write";
223  *   };
224  *
225  *   // grant any code running as "Duke" permission to read
226  *   // the "java.vendor" Property.
227  *
228  *   grant principal foo.com.Principal "Duke" {
229  *         permission java.util.PropertyPermission "java.vendor";
230  *
231  *
232  * </pre>
233  *  This Policy implementation supports special handling of any
234  *  permission that contains the string, "<b>${{self}}</b>", as part of
235  *  its target name.  When such a permission is evaluated
236  *  (such as during a security check), <b>${{self}}</b> is replaced
237  *  with one or more Principal class/name pairs.  The exact
238  *  replacement performed depends upon the contents of the
239  *  grant clause to which the permission belongs.
240  *<p>
241  *
242  *  If the grant clause does not contain any principal information,
243  *  the permission will be ignored (permissions containing
244  *  <b>${{self}}</b> in their target names are only valid in the context
245  *  of a principal-based grant clause).  For example, BarPermission
246  *  will always be ignored in the following grant clause:
247  *
248  *<pre>
249  *    grant codebase "www.foo.com", signedby "duke" {
250  *      permission BarPermission "... ${{self}} ...";
251  *    };
252  *</pre>
253  *
254  *  If the grant clause contains principal information, <b>${{self}}</b>
255  *  will be replaced with that same principal information.
256  *  For example, <b>${{self}}</b> in BarPermission will be replaced by
257  *  <b>javax.security.auth.x500.X500Principal "cn=Duke"</b>
258  *  in the following grant clause:
259  *
260  *  <pre>
261  *    grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
262  *      permission BarPermission "... ${{self}} ...";
263  *    };
264  *  </pre>
265  *
266  *  If there is a comma-separated list of principals in the grant
267  *  clause, then <b>${{self}}</b> will be replaced by the same
268  *  comma-separated list or principals.
269  *  In the case where both the principal class and name are
270  *  wildcarded in the grant clause, <b>${{self}}</b> is replaced
271  *  with all the principals associated with the <code>Subject</code>
272  *  in the current <code>AccessControlContext</code>.
273  *
274  *
275  * <p> For PrivateCredentialPermissions, you can also use "<b>self</b>"
276  * instead of "<b>${{self}}</b>". However the use of "<b>self</b>" is
277  * deprecated in favour of "<b>${{self}}</b>".
278  *
279  * @see java.security.CodeSource
280  * @see java.security.Permissions
281  * @see java.security.ProtectionDomain
282  */
283 public class PolicyFile extends java.security.Policy {
284 
285     private static final Debug debug = Debug.getInstance("policy");
286 
287     private static final String NONE = "NONE";
288     private static final String P11KEYSTORE = "PKCS11";
289 
290     private static final String SELF = "${{self}}";
291     private static final String X500PRINCIPAL =
292                         "javax.security.auth.x500.X500Principal";
293     private static final String POLICY = "java.security.policy";
294     private static final String SECURITY_MANAGER = "java.security.manager";
295     private static final String POLICY_URL = "policy.url.";
296     private static final String AUTH_POLICY = "java.security.auth.policy";
297     private static final String AUTH_POLICY_URL = "auth.policy.url.";
298 
299     private static final int DEFAULT_CACHE_SIZE = 1;
300 
301     // contains the policy grant entries, PD cache, and alias mapping
302     private AtomicReference<PolicyInfo> policyInfo = new AtomicReference<>();
303     private boolean constructed = false;
304 
305     private boolean expandProperties = true;
306     private boolean ignoreIdentityScope = true;
307     private boolean allowSystemProperties = true;
308     private boolean notUtf8 = false;
309     private URL url;
310 
311     // for use with the reflection API
312 
313     private static final Class[] PARAMS0 = { };
314     private static final Class[] PARAMS1 = { String.class };
315     private static final Class[] PARAMS2 = { String.class, String.class };
316 
317     /**
318      * Initializes the Policy object and reads the default policy
319      * configuration file(s) into the Policy object.
320      */
321     public PolicyFile() {
322         init((URL)null);
323     }
324 
325     /**
326      * Initializes the Policy object and reads the default policy
327      * from the specified URL only.
328      */
329     public PolicyFile(URL url) {
330         this.url = url;
331         init(url);
332     }
333 
334     /**
335      * Initializes the Policy object and reads the default policy
336      * configuration file(s) into the Policy object.
337      *
338      * The algorithm for locating the policy file(s) and reading their
339      * information into the Policy object is:
340      * <pre>
341      *   loop through the Security Properties named "policy.url.1",
342      *  ""policy.url.2", "auth.policy.url.1",  "auth.policy.url.2" etc, until
343      *   you don't find one. Each of these specify a policy file.
344      *
345      *   if none of these could be loaded, use a builtin static policy
346      *      equivalent to the default lib/security/java.policy file.
347      *
348      *   if the system property "java.policy" or "java.auth.policy" is defined
349      * (which is the
350      *      case when the user uses the -D switch at runtime), and
351      *     its use is allowed by the security property file,
352      *     also load it.
353      * </pre>
354      *
355      * Each policy file consists of one or more grant entries, each of
356      * which consists of a number of permission entries.
357      * <pre>
358      *   grant signedBy "<i>alias</i>", codeBase "<i>URL</i>" {
359      *     permission <i>Type</i> "<i>name</i>", "<i>action</i>",
360      *         signedBy "<i>alias</i>";
361      *     ....
362      *     permission <i>Type</i> "<i>name</i>", "<i>action</i>",
363      *         signedBy "<i>alias</i>";
364      *   };
365      *
366      * </pre>
367      *
368      * All non-italicized items above must appear as is (although case
369      * doesn't matter and some are optional, as noted below).
370      * Italicized items represent variable values.
371      *
372      * <p> A grant entry must begin with the word <code>grant</code>.
373      * The <code>signedBy</code> and <code>codeBase</code> name/value
374      * pairs are optional.
375      * If they are not present, then any signer (including unsigned code)
376      * will match, and any codeBase will match.
377      *
378      * <p> A permission entry must begin with the word <code>permission</code>.
379      * The word <code><i>Type</i></code> in the template above would actually
380      * be a specific permission type, such as
381      * <code>java.io.FilePermission</code> or
382      * <code>java.lang.RuntimePermission</code>.
383      *
384      * <p>The "<i>action</i>" is required for
385      * many permission types, such as <code>java.io.FilePermission</code>
386      * (where it specifies what type of file access is permitted).
387      * It is not required for categories such as
388      * <code>java.lang.RuntimePermission</code>
389      * where it is not necessary - you either have the
390      * permission specified by the <code>"<i>name</i>"</code>
391      * value following the type name or you don't.
392      *
393      * <p>The <code>signedBy</code> name/value pair for a permission entry
394      * is optional. If present, it indicates a signed permission. That is,
395      * the permission class itself must be signed by the given alias in
396      * order for it to be granted. For example,
397      * suppose you have the following grant entry:
398      *
399      * <pre>
400      *   grant {
401      *     permission Foo "foobar", signedBy "FooSoft";
402      *   }
403      * </pre>
404      *
405      * <p>Then this permission of type <i>Foo</i> is granted if the
406      * <code>Foo.class</code> permission has been signed by the
407      * "FooSoft" alias, or if <code>Foo.class</code> is a
408      * system class (i.e., is found on the CLASSPATH).
409      *
410      * <p>Items that appear in an entry must appear in the specified order
411      * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
412      * "<i>action</i>"). An entry is terminated with a semicolon.
413      *
414      * <p>Case is unimportant for the identifiers (<code>permission</code>,
415      * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
416      * significant for the <i>Type</i>
417      * or for any string that is passed in as a value. <p>
418      *
419      * <p>An example of two entries in a policy configuration file is
420      * <pre>
421      *   //  if the code is signed by "Duke", grant it read/write to all
422      *   // files in /tmp.
423      *
424      *   grant signedBy "Duke" {
425      *          permission java.io.FilePermission "/tmp/*", "read,write";
426      *   };
427      * <p>
428      *   // grant everyone the following permission
429      *
430      *   grant {
431      *     permission java.util.PropertyPermission "java.vendor";
432      *   };
433      *  </pre>
434      */
435     private void init(URL url) {
436         // Properties are set once for each init(); ignore changes between
437         // between diff invocations of initPolicyFile(policy, url, info).
438         String numCacheStr =
439           AccessController.doPrivileged(new PrivilegedAction<String>() {
440             public String run() {
441                 expandProperties = "true".equalsIgnoreCase
442                     (Security.getProperty("policy.expandProperties"));
443                 ignoreIdentityScope = "true".equalsIgnoreCase
444                     (Security.getProperty("policy.ignoreIdentityScope"));
445                 allowSystemProperties = "true".equalsIgnoreCase
446                     (Security.getProperty("policy.allowSystemProperty"));
447                 notUtf8 = "false".equalsIgnoreCase
448                     (System.getProperty("sun.security.policy.utf8"));
449                 return System.getProperty("sun.security.policy.numcaches");
450             }});
451 
452         int numCaches;
453         if (numCacheStr != null) {
454             try {
455                 numCaches = Integer.parseInt(numCacheStr);
456             } catch (NumberFormatException e) {
457                 numCaches = DEFAULT_CACHE_SIZE;
458             }
459         } else {
460             numCaches = DEFAULT_CACHE_SIZE;
461         }
462         // System.out.println("number caches=" + numCaches);
463         PolicyInfo newInfo = new PolicyInfo(numCaches);
464         initPolicyFile(newInfo, url);
465         policyInfo.set(newInfo);
466     }
467 
468     private void initPolicyFile(final PolicyInfo newInfo, final URL url) {
469 
470         if (url != null) {
471 
472             /**
473              * If the caller specified a URL via Policy.getInstance,
474              * we only read from that URL
475              */
476 
477             if (debug != null) {
478                 debug.println("reading "+url);
479             }
480             AccessController.doPrivileged(new PrivilegedAction<Void>() {
481                 public Void run() {
482                     if (init(url, newInfo) == false) {
483                         // use static policy if all else fails
484                         initStaticPolicy(newInfo);
485                     }
486                     return null;
487                 }
488             });
489 
490         } else {
491 
492             /**
493              * Caller did not specify URL via Policy.getInstance.
494              * Read from URLs listed in the java.security properties file.
495              *
496              * We call initPolicyFile with POLICY , POLICY_URL and then
497              * call it with AUTH_POLICY and AUTH_POLICY_URL
498              * So first we will process the JAVA standard policy
499              * and then process the JAVA AUTH Policy.
500              * This is for backward compatibility as well as to handle
501              * cases where the user has a single unified policyfile
502              * with both java policy entries and auth entries
503              */
504 
505             boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo);
506             // To maintain strict backward compatibility
507             // we load the static policy only if POLICY load failed
508             if (!loaded_one) {
509                 // use static policy if all else fails
510                 initStaticPolicy(newInfo);
511             }
512 
513             initPolicyFile(AUTH_POLICY, AUTH_POLICY_URL, newInfo);
514         }
515     }
516 
517     private boolean initPolicyFile(final String propname, final String urlname,
518                                 final PolicyInfo newInfo) {
519         Boolean loadedPolicy =
520             AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
521             public Boolean run() {
522                 boolean loaded_policy = false;
523 
524                 if (allowSystemProperties) {
525                     String extra_policy = System.getProperty(propname);
526                     if (extra_policy != null) {
527                         boolean overrideAll = false;
528                         if (extra_policy.startsWith("=")) {
529                             overrideAll = true;
530                             extra_policy = extra_policy.substring(1);
531                         }
532                         try {
533                             extra_policy =
534                                 PropertyExpander.expand(extra_policy);
535                             URL policyURL;
536 
537                             File policyFile = new File(extra_policy);
538                             if (policyFile.exists()) {
539                                 policyURL = ParseUtil.fileToEncodedURL
540                                     (new File(policyFile.getCanonicalPath()));
541                             } else {
542                                 policyURL = new URL(extra_policy);
543                             }
544                             if (debug != null)
545                                 debug.println("reading "+policyURL);
546                             if (init(policyURL, newInfo))
547                                 loaded_policy = true;
548                         } catch (Exception e) {
549                             // ignore.
550                             if (debug != null) {
551                                 debug.println("caught exception: "+e);
552                             }
553                         }
554                         if (overrideAll) {
555                             if (debug != null) {
556                                 debug.println("overriding other policies!");
557                             }
558                             return Boolean.valueOf(loaded_policy);
559                         }
560                     }
561                 }
562 
563                 int n = 1;
564                 String policy_uri;
565 
566                 while ((policy_uri = Security.getProperty(urlname+n)) != null) {
567                     try {
568                         URL policy_url = null;
569                         String expanded_uri = PropertyExpander.expand
570                                 (policy_uri).replace(File.separatorChar, '/');
571 
572                         if (policy_uri.startsWith("file:${java.home}/") ||
573                             policy_uri.startsWith("file:${user.home}/")) {
574 
575                             // this special case accommodates
576                             // the situation java.home/user.home
577                             // expand to a single slash, resulting in
578                             // a file://foo URI
579                             policy_url = new File
580                                 (expanded_uri.substring(5)).toURI().toURL();
581                         } else {
582                             policy_url = new URI(expanded_uri).toURL();
583                         }
584 
585                         if (debug != null)
586                             debug.println("reading "+policy_url);
587                         if (init(policy_url, newInfo))
588                             loaded_policy = true;
589                     } catch (Exception e) {
590                         if (debug != null) {
591                             debug.println("error reading policy "+e);
592                             e.printStackTrace();
593                         }
594                         // ignore that policy
595                     }
596                     n++;
597                 }
598                 return Boolean.valueOf(loaded_policy);
599             }
600         });
601 
602         return loadedPolicy.booleanValue();
603     }
604 
605     /**
606      * Reads a policy configuration into the Policy object using a
607      * Reader object.
608      *
609      * @param policyFile the policy Reader object.
610      */
611     private boolean init(URL policy, PolicyInfo newInfo) {
612         boolean success = false;
613         PolicyParser pp = new PolicyParser(expandProperties);
614         InputStreamReader isr = null;
615         try {
616 
617             // read in policy using UTF-8 by default
618             //
619             // check non-standard system property to see if
620             // the default encoding should be used instead
621 
622             if (notUtf8) {
623                 isr = new InputStreamReader
624                                 (PolicyUtil.getInputStream(policy));
625             } else {
626                 isr = new InputStreamReader
627                                 (PolicyUtil.getInputStream(policy), "UTF-8");
628             }
629 
630             pp.read(isr);
631 
632             KeyStore keyStore = null;
633             try {
634                 keyStore = PolicyUtil.getKeyStore
635                                 (policy,
636                                 pp.getKeyStoreUrl(),
637                                 pp.getKeyStoreType(),
638                                 pp.getKeyStoreProvider(),
639                                 pp.getStorePassURL(),
640                                 debug);
641             } catch (Exception e) {
642                 // ignore, treat it like we have no keystore
643                 if (debug != null) {
644                     e.printStackTrace();
645                 }
646             }
647 
648             Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements();
649             while (enum_.hasMoreElements()) {
650                 PolicyParser.GrantEntry ge = enum_.nextElement();
651                 addGrantEntry(ge, keyStore, newInfo);
652             }
653         } catch (PolicyParser.ParsingException pe) {
654             MessageFormat form = new MessageFormat(ResourcesMgr.getString
655                 (POLICY + ".error.parsing.policy.message"));
656             Object[] source = {policy, pe.getLocalizedMessage()};
657             System.err.println(form.format(source));
658             if (debug != null)
659                 pe.printStackTrace();
660 
661         } catch (Exception e) {
662             if (debug != null) {
663                 debug.println("error parsing "+policy);
664                 debug.println(e.toString());
665                 e.printStackTrace();
666             }
667         } finally {
668             if (isr != null) {
669                 try {
670                     isr.close();
671                     success = true;
672                 } catch (IOException e) {
673                     // ignore the exception
674                 }
675             } else {
676                 success = true;
677             }
678         }
679 
680         return success;
681     }
682 
683     private void initStaticPolicy(final PolicyInfo newInfo) {
684         AccessController.doPrivileged(new PrivilegedAction<Void>() {
685             public Void run() {
686                 PolicyEntry pe = new PolicyEntry(new CodeSource(null,
687                     (Certificate[]) null));
688                 pe.add(SecurityConstants.LOCAL_LISTEN_PERMISSION);
689                 pe.add(new PropertyPermission("java.version",
690                     SecurityConstants.PROPERTY_READ_ACTION));
691                 pe.add(new PropertyPermission("java.vendor",
692                     SecurityConstants.PROPERTY_READ_ACTION));
693                 pe.add(new PropertyPermission("java.vendor.url",
694                     SecurityConstants.PROPERTY_READ_ACTION));
695                 pe.add(new PropertyPermission("java.class.version",
696                     SecurityConstants.PROPERTY_READ_ACTION));
697                 pe.add(new PropertyPermission("os.name",
698                     SecurityConstants.PROPERTY_READ_ACTION));
699                 pe.add(new PropertyPermission("os.version",
700                     SecurityConstants.PROPERTY_READ_ACTION));
701                 pe.add(new PropertyPermission("os.arch",
702                     SecurityConstants.PROPERTY_READ_ACTION));
703                 pe.add(new PropertyPermission("file.separator",
704                     SecurityConstants.PROPERTY_READ_ACTION));
705                 pe.add(new PropertyPermission("path.separator",
706                     SecurityConstants.PROPERTY_READ_ACTION));
707                 pe.add(new PropertyPermission("line.separator",
708                     SecurityConstants.PROPERTY_READ_ACTION));
709                 pe.add(new PropertyPermission
710                                 ("java.specification.version",
711                                     SecurityConstants.PROPERTY_READ_ACTION));
712                 pe.add(new PropertyPermission
713                                 ("java.specification.vendor",
714                                     SecurityConstants.PROPERTY_READ_ACTION));
715                 pe.add(new PropertyPermission
716                                 ("java.specification.name",
717                                     SecurityConstants.PROPERTY_READ_ACTION));
718                 pe.add(new PropertyPermission
719                                 ("java.vm.specification.version",
720                                     SecurityConstants.PROPERTY_READ_ACTION));
721                 pe.add(new PropertyPermission
722                                 ("java.vm.specification.vendor",
723                                     SecurityConstants.PROPERTY_READ_ACTION));
724                 pe.add(new PropertyPermission
725                                 ("java.vm.specification.name",
726                                     SecurityConstants.PROPERTY_READ_ACTION));
727                 pe.add(new PropertyPermission("java.vm.version",
728                     SecurityConstants.PROPERTY_READ_ACTION));
729                 pe.add(new PropertyPermission("java.vm.vendor",
730                     SecurityConstants.PROPERTY_READ_ACTION));
731                 pe.add(new PropertyPermission("java.vm.name",
732                     SecurityConstants.PROPERTY_READ_ACTION));
733 
734                 // No need to sync because noone has access to newInfo yet
735                 newInfo.policyEntries.add(pe);
736 
737                 // Add AllPermissions for standard extensions
738                 String[] extCodebases = PolicyParser.parseExtDirs(
739                     PolicyParser.EXTDIRS_EXPANSION, 0);
740                 if (extCodebases != null && extCodebases.length > 0) {
741                     for (int i = 0; i < extCodebases.length; i++) {
742                         try {
743                             pe = new PolicyEntry(canonicalizeCodebase(
744                                 new CodeSource(new URL(extCodebases[i]),
745                                     (Certificate[]) null), false ));
746                             pe.add(SecurityConstants.ALL_PERMISSION);
747 
748                             // No need to sync because noone has access to
749                             // newInfo yet
750                             newInfo.policyEntries.add(pe);
751                         } catch (Exception e) {
752                             // this is probably bad (though not dangerous).
753                             // What should we do?
754                         }
755                     }
756                 }
757                 return null;
758             }
759         });
760     }
761 
762     /**
763      * Given a GrantEntry, create a codeSource.
764      *
765      * @return null if signedBy alias is not recognized
766      */
767     private CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore,
768         PolicyInfo newInfo) throws java.net.MalformedURLException
769     {
770         Certificate[] certs = null;
771         if (ge.signedBy != null) {
772             certs = getCertificates(keyStore, ge.signedBy, newInfo);
773             if (certs == null) {
774                 // we don't have a key for this alias,
775                 // just return
776                 if (debug != null) {
777                     debug.println("  -- No certs for alias '" +
778                                        ge.signedBy + "' - ignoring entry");
779                 }
780                 return null;
781             }
782         }
783 
784         URL location;
785 
786         if (ge.codeBase != null)
787             location = new URL(ge.codeBase);
788         else
789             location = null;
790 
791         return (canonicalizeCodebase(new CodeSource(location, certs),false));
792     }
793 
794     /**
795      * Add one policy entry to the list.
796      */
797     private void addGrantEntry(PolicyParser.GrantEntry ge,
798                                KeyStore keyStore, PolicyInfo newInfo) {
799 
800         if (debug != null) {
801             debug.println("Adding policy entry: ");
802             debug.println("  signedBy " + ge.signedBy);
803             debug.println("  codeBase " + ge.codeBase);
804             if (ge.principals != null && ge.principals.size() > 0) {
805                 ListIterator<PolicyParser.PrincipalEntry> li =
806                                                 ge.principals.listIterator();
807                 while (li.hasNext()) {
808                     PolicyParser.PrincipalEntry pppe = li.next();
809                 debug.println("  " + pppe.toString());
810                 }
811             }
812         }
813 
814         try {
815             CodeSource codesource = getCodeSource(ge, keyStore, newInfo);
816             // skip if signedBy alias was unknown...
817             if (codesource == null) return;
818 
819             // perform keystore alias principal replacement.
820             // for example, if alias resolves to X509 certificate,
821             // replace principal with:  <X500Principal class>  <SubjectDN>
822             // -- skip if alias is unknown
823             if (replacePrincipals(ge.principals, keyStore) == false)
824                 return;
825             PolicyEntry entry = new PolicyEntry(codesource, ge.principals);
826             Enumeration<PolicyParser.PermissionEntry> enum_ =
827                                                 ge.permissionElements();
828             while (enum_.hasMoreElements()) {
829                 PolicyParser.PermissionEntry pe = enum_.nextElement();
830 
831                 try {
832                     // perform ${{ ... }} expansions within permission name
833                     expandPermissionName(pe, keyStore);
834 
835                     // XXX special case PrivateCredentialPermission-SELF
836                     Permission perm;
837                     if (pe.permission.equals
838                         ("javax.security.auth.PrivateCredentialPermission") &&
839                         pe.name.endsWith(" self")) {
840                         pe.name = pe.name.substring(0, pe.name.indexOf("self"))
841                                 + SELF;
842                     }
843                     // check for self
844                     if (pe.name != null && pe.name.indexOf(SELF) != -1) {
845                         // Create a "SelfPermission" , it could be an
846                         // an unresolved permission which will be resolved
847                         // when implies is called
848                         // Add it to entry
849                         Certificate certs[];
850                         if (pe.signedBy != null) {
851                             certs = getCertificates(keyStore,
852                                                     pe.signedBy,
853                                                     newInfo);
854                         } else {
855                             certs = null;
856                         }
857                         perm = new SelfPermission(pe.permission,
858                                                   pe.name,
859                                                   pe.action,
860                                                   certs);
861                     } else {
862                         perm = getInstance(pe.permission,
863                                            pe.name,
864                                            pe.action);
865                     }
866                     entry.add(perm);
867                     if (debug != null) {
868                         debug.println("  "+perm);
869                     }
870                 } catch (ClassNotFoundException cnfe) {
871                     Certificate certs[];
872                     if (pe.signedBy != null) {
873                         certs = getCertificates(keyStore,
874                                                 pe.signedBy,
875                                                 newInfo);
876                     } else {
877                         certs = null;
878                     }
879 
880                     // only add if we had no signer or we had a
881                     // a signer and found the keys for it.
882                     if (certs != null || pe.signedBy == null) {
883                         Permission perm = new UnresolvedPermission(
884                                                   pe.permission,
885                                                   pe.name,
886                                                   pe.action,
887                                                   certs);
888                         entry.add(perm);
889                         if (debug != null) {
890                             debug.println("  "+perm);
891                         }
892                     }
893                 } catch (java.lang.reflect.InvocationTargetException ite) {
894                     MessageFormat form = new MessageFormat
895                         (ResourcesMgr.getString
896                          (POLICY +
897                           ".error.adding.Permission.perm.message"));
898                     Object[] source = {pe.permission,
899                                        ite.getTargetException().toString()};
900                     System.err.println(form.format(source));
901                 } catch (Exception e) {
902                     MessageFormat form = new MessageFormat
903                         (ResourcesMgr.getString
904                          (POLICY +
905                           ".error.adding.Permission.perm.message"));
906                     Object[] source = {pe.permission,
907                                        e.toString()};
908                     System.err.println(form.format(source));
909                 }
910             }
911 
912             // No need to sync because noone has access to newInfo yet
913             newInfo.policyEntries.add(entry);
914         } catch (Exception e) {
915             MessageFormat form = new MessageFormat(ResourcesMgr.getString
916                                          (POLICY
917                                          + ".error.adding.Entry.message"));
918             Object[] source = {e.toString()};
919             System.err.println(form.format(source));
920         }
921         if (debug != null)
922             debug.println();
923     }
924 
925     /**
926      * Returns a new Permission object of the given Type. The Permission is
927      * created by getting the
928      * Class object using the <code>Class.forName</code> method, and using
929      * the reflection API to invoke the (String name, String actions)
930      * constructor on the
931      * object.
932      *
933      * @param type the type of Permission being created.
934      * @param name the name of the Permission being created.
935      * @param actions the actions of the Permission being created.
936      *
937      * @exception  ClassNotFoundException  if the particular Permission
938      *             class could not be found.
939      *
940      * @exception  IllegalAccessException  if the class or initializer is
941      *               not accessible.
942      *
943      * @exception  InstantiationException  if getInstance tries to
944      *               instantiate an abstract class or an interface, or if the
945      *               instantiation fails for some other reason.
946      *
947      * @exception  NoSuchMethodException if the (String, String) constructor
948      *               is not found.
949      *
950      * @exception  InvocationTargetException if the underlying Permission
951      *               constructor throws an exception.
952      *
953      */
954 
955     private static final Permission getInstance(String type,
956                                     String name,
957                                     String actions)
958         throws ClassNotFoundException,
959                InstantiationException,
960                IllegalAccessException,
961                NoSuchMethodException,
962                InvocationTargetException
963     {
964         //XXX we might want to keep a hash of created factories...
965         Class<?> pc = Class.forName(type);
966         Permission answer = getKnownInstance(pc, name, actions);
967         if (answer != null) {
968             return answer;
969         }
970 
971         if (name == null && actions == null) {
972             try {
973                 Constructor<?> c = pc.getConstructor(PARAMS0);
974                 return (Permission) c.newInstance(new Object[] {});
975             } catch (NoSuchMethodException ne) {
976                 try {
977                     Constructor<?> c = pc.getConstructor(PARAMS1);
978                     return (Permission) c.newInstance(
979                               new Object[] { name});
980                 } catch (NoSuchMethodException ne1 ) {
981                     Constructor<?> c = pc.getConstructor(PARAMS2);
982                     return (Permission) c.newInstance(
983                         new Object[] { name, actions });
984                 }
985             }
986         } else {
987             if (name != null && actions == null) {
988                 try {
989                     Constructor<?> c = pc.getConstructor(PARAMS1);
990                     return (Permission) c.newInstance(new Object[] { name});
991                 } catch (NoSuchMethodException ne) {
992                     Constructor<?> c = pc.getConstructor(PARAMS2);
993                     return (Permission) c.newInstance(
994                           new Object[] { name, actions });
995                 }
996             } else {
997                 Constructor<?> c = pc.getConstructor(PARAMS2);
998                 return (Permission) c.newInstance(
999                       new Object[] { name, actions });
1000              }
1001         }
1002     }
1003 
1004     /**
1005      * Creates one of the well-known permissions directly instead of
1006      * via reflection. Keep list short to not penalize non-JDK-defined
1007      * permissions.
1008      */
1009     private static final Permission getKnownInstance(Class claz,
1010         String name, String actions) {
1011         // XXX shorten list to most popular ones?
1012         if (claz.equals(FilePermission.class)) {
1013             return new FilePermission(name, actions);
1014         } else if (claz.equals(SocketPermission.class)) {
1015             return new SocketPermission(name, actions);
1016         } else if (claz.equals(RuntimePermission.class)) {
1017             return new RuntimePermission(name, actions);
1018         } else if (claz.equals(PropertyPermission.class)) {
1019             return new PropertyPermission(name, actions);
1020         } else if (claz.equals(NetPermission.class)) {
1021             return new NetPermission(name, actions);
1022         } else if (claz.equals(AllPermission.class)) {
1023             return SecurityConstants.ALL_PERMISSION;
1024 /*
1025         } else if (claz.equals(ReflectPermission.class)) {
1026             return new ReflectPermission(name, actions);
1027         } else if (claz.equals(SecurityPermission.class)) {
1028             return new SecurityPermission(name, actions);
1029         } else if (claz.equals(PrivateCredentialPermission.class)) {
1030             return new PrivateCredentialPermission(name, actions);
1031         } else if (claz.equals(AuthPermission.class)) {
1032             return new AuthPermission(name, actions);
1033         } else if (claz.equals(ServicePermission.class)) {
1034             return new ServicePermission(name, actions);
1035         } else if (claz.equals(DelegationPermission.class)) {
1036             return new DelegationPermission(name, actions);
1037         } else if (claz.equals(SerializablePermission.class)) {
1038             return new SerializablePermission(name, actions);
1039         } else if (claz.equals(AudioPermission.class)) {
1040             return new AudioPermission(name, actions);
1041         } else if (claz.equals(SSLPermission.class)) {
1042             return new SSLPermission(name, actions);
1043         } else if (claz.equals(LoggingPermission.class)) {
1044             return new LoggingPermission(name, actions);
1045         } else if (claz.equals(SQLPermission.class)) {
1046             return new SQLPermission(name, actions);
1047 */
1048         } else {
1049             return null;
1050         }
1051     }
1052 
1053     /**
1054      * Fetch all certs associated with this alias.
1055      */
1056     private Certificate[] getCertificates
1057                 (KeyStore keyStore, String aliases, PolicyInfo newInfo) {
1058 
1059         List<Certificate> vcerts = null;
1060 
1061         StringTokenizer st = new StringTokenizer(aliases, ",");
1062         int n = 0;
1063 
1064         while (st.hasMoreTokens()) {
1065             String alias = st.nextToken().trim();
1066             n++;
1067             Certificate cert = null;
1068             // See if this alias's cert has already been cached
1069             synchronized (newInfo.aliasMapping) {
1070                 cert = (Certificate)newInfo.aliasMapping.get(alias);
1071 
1072                 if (cert == null && keyStore != null) {
1073 
1074                     try {
1075                         cert = keyStore.getCertificate(alias);
1076                     } catch (KeyStoreException kse) {
1077                         // never happens, because keystore has already been loaded
1078                         // when we call this
1079                     }
1080                     if (cert != null) {
1081                         newInfo.aliasMapping.put(alias, cert);
1082                         newInfo.aliasMapping.put(cert, alias);
1083                     }
1084                 }
1085             }
1086 
1087             if (cert != null) {
1088                 if (vcerts == null)
1089                     vcerts = new ArrayList<Certificate>();
1090                 vcerts.add(cert);
1091             }
1092         }
1093 
1094         // make sure n == vcerts.size, since we are doing a logical *and*
1095         if (vcerts != null && n == vcerts.size()) {
1096             Certificate[] certs = new Certificate[vcerts.size()];
1097             vcerts.toArray(certs);
1098             return certs;
1099         } else {
1100             return null;
1101         }
1102     }
1103 
1104     /**
1105      * Refreshes the policy object by re-reading all the policy files.
1106      */
1107     @Override public void refresh() {
1108         init(url);
1109     }
1110 
1111     /**
1112      * Evaluates the the global policy for the permissions granted to
1113      * the ProtectionDomain and tests whether the permission is
1114      * granted.
1115      *
1116      * @param domain the ProtectionDomain to test
1117      * @param permission the Permission object to be tested for implication.
1118      *
1119      * @return true if "permission" is a proper subset of a permission
1120      * granted to this ProtectionDomain.
1121      *
1122      * @see java.security.ProtectionDomain
1123      */
1124     @Override
1125     public boolean implies(ProtectionDomain pd, Permission p) {
1126         PolicyInfo pi = policyInfo.get();
1127         ProtectionDomainCache pdMap = pi.getPdMapping();
1128 
1129         PermissionCollection pc = pdMap.get(pd);
1130 
1131         if (pc != null) {
1132             return pc.implies(p);
1133         }
1134 
1135         pc = getPermissions(pd);
1136         if (pc == null) {
1137             return false;
1138         }
1139 
1140         // cache mapping of protection domain to its PermissionCollection
1141         pdMap.put(pd, pc);
1142         return pc.implies(p);
1143     }
1144 
1145     /**
1146      * Examines this <code>Policy</code> and returns the permissions granted
1147      * to the specified <code>ProtectionDomain</code>.  This includes
1148      * the permissions currently associated with the domain as well
1149      * as the policy permissions granted to the domain's
1150      * CodeSource, ClassLoader, and Principals.
1151      *
1152      * <p> Note that this <code>Policy</code> implementation has
1153      * special handling for PrivateCredentialPermissions.
1154      * When this method encounters a <code>PrivateCredentialPermission</code>
1155      * which specifies "self" as the <code>Principal</code> class and name,
1156      * it does not add that <code>Permission</code> to the returned
1157      * <code>PermissionCollection</code>.  Instead, it builds
1158      * a new <code>PrivateCredentialPermission</code>
1159      * for each <code>Principal</code> associated with the provided
1160      * <code>Subject</code>.  Each new <code>PrivateCredentialPermission</code>
1161      * contains the same Credential class as specified in the
1162      * originally granted permission, as well as the Class and name
1163      * for the respective <code>Principal</code>.
1164      *
1165      * <p>
1166      *
1167      * @param domain the Permissions granted to this
1168      *          <code>ProtectionDomain</code> are returned.
1169      *
1170      * @return the Permissions granted to the provided
1171      *          <code>ProtectionDomain</code>.
1172      */
1173     @Override
1174     public PermissionCollection getPermissions(ProtectionDomain domain) {
1175         Permissions perms = new Permissions();
1176 
1177         if (domain == null)
1178            return perms;
1179 
1180         // first get policy perms
1181         getPermissions(perms, domain);
1182 
1183         // add static perms
1184         //      - adding static perms after policy perms is necessary
1185         //        to avoid a regression for 4301064
1186         PermissionCollection pc = domain.getPermissions();
1187         if (pc != null) {
1188             synchronized (pc) {
1189                 Enumeration<Permission> e = pc.elements();
1190                 while (e.hasMoreElements()) {
1191                     perms.add(e.nextElement());
1192                 }
1193             }
1194         }
1195 
1196         return perms;
1197     }
1198 
1199     /**
1200      * Examines this Policy and creates a PermissionCollection object with
1201      * the set of permissions for the specified CodeSource.
1202      *
1203      * @param CodeSource the codesource associated with the caller.
1204      * This encapsulates the original location of the code (where the code
1205      * came from) and the public key(s) of its signer.
1206      *
1207      * @return the set of permissions according to the policy.
1208      */
1209     @Override
1210     public PermissionCollection getPermissions(CodeSource codesource) {
1211         return getPermissions(new Permissions(), codesource);
1212     }
1213 
1214     /**
1215      * Examines the global policy and returns the provided Permissions
1216      * object with additional permissions granted to the specified
1217      * ProtectionDomain.
1218      *
1219      * @param perm the Permissions to populate
1220      * @param pd the ProtectionDomain associated with the caller.
1221      *
1222      * @return the set of Permissions according to the policy.
1223      */
1224     private PermissionCollection getPermissions(Permissions perms,
1225                                         ProtectionDomain pd ) {
1226         if (debug != null) {
1227             debug.println("getPermissions:\n\t" + printPD(pd));
1228         }
1229 
1230         final CodeSource cs = pd.getCodeSource();
1231         if (cs == null)
1232             return perms;
1233 
1234         CodeSource canonCodeSource = AccessController.doPrivileged(
1235             new java.security.PrivilegedAction<CodeSource>(){
1236                 public CodeSource run() {
1237                     return canonicalizeCodebase(cs, true);
1238                 }
1239             });
1240         return getPermissions(perms, canonCodeSource, pd.getPrincipals());
1241     }
1242 
1243     /**
1244      * Examines the global policy and returns the provided Permissions
1245      * object with additional permissions granted to the specified
1246      * CodeSource.
1247      *
1248      * @param permissions the permissions to populate
1249      * @param codesource the codesource associated with the caller.
1250      * This encapsulates the original location of the code (where the code
1251      * came from) and the public key(s) of its signer.
1252      *
1253      * @return the set of permissions according to the policy.
1254      */
1255     private PermissionCollection getPermissions(Permissions perms,
1256                                final CodeSource cs) {
1257 
1258         CodeSource canonCodeSource = AccessController.doPrivileged(
1259             new java.security.PrivilegedAction<CodeSource>(){
1260                 public CodeSource run() {
1261                     return canonicalizeCodebase(cs, true);
1262                 }
1263             });
1264 
1265         return getPermissions(perms, canonCodeSource, null);
1266     }
1267 
1268     private Permissions getPermissions(Permissions perms,
1269                                        final CodeSource cs,
1270                                        Principal[] principals) {
1271         PolicyInfo pi = policyInfo.get();
1272 
1273         for (PolicyEntry entry : pi.policyEntries) {
1274             addPermissions(perms, cs, principals, entry);
1275         }
1276 
1277         // Go through policyEntries gotten from identity db; sync required
1278         // because checkForTrustedIdentity (below) might update list
1279         synchronized (pi.identityPolicyEntries) {
1280             for (PolicyEntry entry : pi.identityPolicyEntries) {
1281                 addPermissions(perms, cs, principals, entry);
1282             }
1283         }
1284 
1285         // now see if any of the keys are trusted ids.
1286         if (!ignoreIdentityScope) {
1287             Certificate certs[] = cs.getCertificates();
1288             if (certs != null) {
1289                 for (int k=0; k < certs.length; k++) {
1290                     Object idMap = pi.aliasMapping.get(certs[k]);
1291                     if (idMap == null &&
1292                         checkForTrustedIdentity(certs[k], pi)) {
1293                         // checkForTrustedIdentity added it
1294                         // to the policy for us. next time
1295                         // around we'll find it. This time
1296                         // around we need to add it.
1297                         perms.add(SecurityConstants.ALL_PERMISSION);
1298                     }
1299                 }
1300             }
1301         }
1302         return perms;
1303     }
1304 
1305     private void addPermissions(Permissions perms,
1306         final CodeSource cs,
1307         Principal[] principals,
1308         final PolicyEntry entry) {
1309 
1310         if (debug != null) {
1311             debug.println("evaluate codesources:\n" +
1312                 "\tPolicy CodeSource: " + entry.getCodeSource() + "\n" +
1313                 "\tActive CodeSource: " + cs);
1314         }
1315 
1316         // check to see if the CodeSource implies
1317         Boolean imp = AccessController.doPrivileged
1318             (new PrivilegedAction<Boolean>() {
1319             public Boolean run() {
1320                 return new Boolean(entry.getCodeSource().implies(cs));
1321             }
1322         });
1323         if (!imp.booleanValue()) {
1324             if (debug != null) {
1325                 debug.println("evaluation (codesource) failed");
1326             }
1327 
1328             // CodeSource does not imply - return and try next policy entry
1329             return;
1330         }
1331 
1332         // check to see if the Principals imply
1333 
1334         List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();
1335         if (debug != null) {
1336             ArrayList<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();
1337             if (principals != null) {
1338                 for (int i = 0; i < principals.length; i++) {
1339                     accPs.add(new PolicyParser.PrincipalEntry
1340                                         (principals[i].getClass().getName(),
1341                                         principals[i].getName()));
1342                 }
1343             }
1344             debug.println("evaluate principals:\n" +
1345                 "\tPolicy Principals: " + entryPs + "\n" +
1346                 "\tActive Principals: " + accPs);
1347         }
1348 
1349         if (entryPs == null || entryPs.size() == 0) {
1350 
1351             // policy entry has no principals -
1352             // add perms regardless of principals in current ACC
1353 
1354             addPerms(perms, principals, entry);
1355             if (debug != null) {
1356                 debug.println("evaluation (codesource/principals) passed");
1357             }
1358             return;
1359 
1360         } else if (principals == null || principals.length == 0) {
1361 
1362             // current thread has no principals but this policy entry
1363             // has principals - perms are not added
1364 
1365             if (debug != null) {
1366                 debug.println("evaluation (principals) failed");
1367             }
1368             return;
1369         }
1370 
1371         // current thread has principals and this policy entry
1372         // has principals.  see if policy entry principals match
1373         // principals in current ACC
1374 
1375         for (int i = 0; i < entryPs.size(); i++) {
1376             PolicyParser.PrincipalEntry pppe = entryPs.get(i);
1377 
1378             // see if principal entry is a PrincipalComparator
1379 
1380             try {
1381                 Class<?> pClass = Class.forName
1382                                 (pppe.principalClass,
1383                                 true,
1384                                 Thread.currentThread().getContextClassLoader());
1385 
1386                 if (!PrincipalComparator.class.isAssignableFrom(pClass)) {
1387 
1388                     // common case - dealing with regular Principal class.
1389                     // see if policy entry principal is in current ACC
1390 
1391                     if (!checkEntryPs(principals, pppe)) {
1392                         if (debug != null) {
1393                             debug.println("evaluation (principals) failed");
1394                         }
1395 
1396                         // policy entry principal not in current ACC -
1397                         // immediately return and go to next policy entry
1398                         return;
1399                     }
1400 
1401                 } else {
1402 
1403                     // dealing with a PrincipalComparator
1404 
1405                     Constructor<?> c = pClass.getConstructor(PARAMS1);
1406                     PrincipalComparator pc = (PrincipalComparator)c.newInstance
1407                                         (new Object[] { pppe.principalName });
1408 
1409                     if (debug != null) {
1410                         debug.println("found PrincipalComparator " +
1411                                         pc.getClass().getName());
1412                     }
1413 
1414                     // check if the PrincipalComparator
1415                     // implies the current thread's principals
1416 
1417                     Set<Principal> pSet = new HashSet<>(principals.length);
1418                     for (int j = 0; j < principals.length; j++) {
1419                         pSet.add(principals[j]);
1420                     }
1421                     Subject subject = new Subject(true,
1422                                                 pSet,
1423                                                 Collections.EMPTY_SET,
1424                                                 Collections.EMPTY_SET);
1425 
1426                     if (!pc.implies(subject)) {
1427                         if (debug != null) {
1428                             debug.println
1429                                 ("evaluation (principal comparator) failed");
1430                         }
1431 
1432                         // policy principal does not imply the current Subject -
1433                         // immediately return and go to next policy entry
1434                         return;
1435                     }
1436                 }
1437             } catch (Exception e) {
1438                 // fall back to regular principal comparison.
1439                 // see if policy entry principal is in current ACC
1440 
1441                 if (debug != null) {
1442                     e.printStackTrace();
1443                 }
1444 
1445                 if (!checkEntryPs(principals, pppe)) {
1446                     if (debug != null) {
1447                         debug.println("evaluation (principals) failed");
1448                     }
1449 
1450                     // policy entry principal not in current ACC -
1451                     // immediately return and go to next policy entry
1452                     return;
1453                 }
1454             }
1455 
1456             // either the principal information matched,
1457             // or the PrincipalComparator.implies succeeded.
1458             // continue loop and test the next policy principal
1459         }
1460 
1461         // all policy entry principals were found in the current ACC -
1462         // grant the policy permissions
1463 
1464         if (debug != null) {
1465             debug.println("evaluation (codesource/principals) passed");
1466         }
1467         addPerms(perms, principals, entry);
1468     }
1469 
1470     private void addPerms(Permissions perms,
1471                         Principal[] accPs,
1472                         PolicyEntry entry) {
1473         for (int i = 0; i < entry.permissions.size(); i++) {
1474             Permission p = entry.permissions.get(i);
1475             if (debug != null) {
1476                 debug.println("  granting " + p);
1477             }
1478 
1479             if (p instanceof SelfPermission) {
1480                 // handle "SELF" permissions
1481                 expandSelf((SelfPermission)p,
1482                         entry.getPrincipals(),
1483                         accPs,
1484                         perms);
1485             } else {
1486                 perms.add(p);
1487             }
1488         }
1489     }
1490 
1491     /**
1492      * This method returns, true, if the principal in the policy entry,
1493      * pppe, is part of the current thread's principal array, pList.
1494      * This method also returns, true, if the policy entry's principal
1495      * is appropriately wildcarded.
1496      *
1497      * Note that the provided <i>pppe</i> argument may have
1498      * wildcards (*) for both the <code>Principal</code> class and name.
1499      *
1500      * @param pList an array of principals from the current thread's
1501      *          AccessControlContext.
1502      *
1503      * @param pppe a Principal specified in a policy grant entry.
1504      *
1505      * @return true if the current thread's pList "contains" the
1506      *          principal in the policy entry, pppe.  This method
1507      *          also returns true if the policy entry's principal
1508      *          appropriately wildcarded.
1509      */
1510     private boolean checkEntryPs(Principal[] pList,
1511                                 PolicyParser.PrincipalEntry pppe) {
1512 
1513         for (int i = 0; i < pList.length; i++) {
1514 
1515             if (pppe.principalClass.equals
1516                         (PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
1517                 pppe.principalClass.equals
1518                         (pList[i].getClass().getName())) {
1519 
1520                 if (pppe.principalName.equals
1521                         (PolicyParser.PrincipalEntry.WILDCARD_NAME) ||
1522                     pppe.principalName.equals
1523                         (pList[i].getName())) {
1524 
1525                     return true;
1526                 }
1527             }
1528         }
1529         return false;
1530     }
1531 
1532     /**
1533      * <p>
1534      *
1535      * @param sp the SelfPermission that needs to be expanded <p>
1536      *
1537      * @param entryPs list of principals for the Policy entry.
1538      *
1539      * @param pdp Principal array from the current ProtectionDomain.
1540      *
1541      * @param perms the PermissionCollection where the individual
1542      *                  Permissions will be added after expansion.
1543      */
1544 
1545     private void expandSelf(SelfPermission sp,
1546                             List<PolicyParser.PrincipalEntry> entryPs,
1547                             Principal[] pdp,
1548                             Permissions perms) {
1549 
1550         if (entryPs == null || entryPs.size() == 0) {
1551             // No principals in the grant to substitute
1552             if (debug != null) {
1553                 debug.println("Ignoring permission "
1554                                 + sp.getSelfType()
1555                                 + " with target name ("
1556                                 + sp.getSelfName() + ").  "
1557                                 + "No Principal(s) specified "
1558                                 + "in the grant clause.  "
1559                                 + "SELF-based target names are "
1560                                 + "only valid in the context "
1561                                 + "of a Principal-based grant entry."
1562                              );
1563             }
1564             return;
1565         }
1566         int startIndex = 0;
1567         int v;
1568         StringBuilder sb = new StringBuilder();
1569         while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) {
1570 
1571             // add non-SELF string
1572             sb.append(sp.getSelfName().substring(startIndex, v));
1573 
1574             // expand SELF
1575             ListIterator<PolicyParser.PrincipalEntry> pli =
1576                                                 entryPs.listIterator();
1577             while (pli.hasNext()) {
1578                 PolicyParser.PrincipalEntry pppe = pli.next();
1579                 String[][] principalInfo = getPrincipalInfo(pppe,pdp);
1580                 for (int i = 0; i < principalInfo.length; i++) {
1581                     if (i != 0) {
1582                         sb.append(", ");
1583                     }
1584                     sb.append(principalInfo[i][0] + " " +
1585                         "\"" + principalInfo[i][1] + "\"");
1586                 }
1587                 if (pli.hasNext()) {
1588                     sb.append(", ");
1589                 }
1590             }
1591             startIndex = v + SELF.length();
1592         }
1593         // add remaining string (might be the entire string)
1594         sb.append(sp.getSelfName().substring(startIndex));
1595 
1596         if (debug != null) {
1597             debug.println("  expanded:\n\t" + sp.getSelfName()
1598                         + "\n  into:\n\t" + sb.toString());
1599         }
1600         try {
1601             // first try to instantiate the permission
1602             perms.add(getInstance(sp.getSelfType(),
1603                                 sb.toString(),
1604                                 sp.getSelfActions()));
1605         } catch (ClassNotFoundException cnfe) {
1606             // ok, the permission is not in the bootclasspath.
1607             // before we add an UnresolvedPermission, check to see
1608             // whether this perm already belongs to the collection.
1609             // if so, use that perm's ClassLoader to create a new
1610             // one.
1611             Class<?> pc = null;
1612             synchronized (perms) {
1613                 Enumeration<Permission> e = perms.elements();
1614                 while (e.hasMoreElements()) {
1615                     Permission pElement = e.nextElement();
1616                     if (pElement.getClass().getName().equals(sp.getSelfType())) {
1617                         pc = pElement.getClass();
1618                         break;
1619                     }
1620                 }
1621             }
1622             if (pc == null) {
1623                 // create an UnresolvedPermission
1624                 perms.add(new UnresolvedPermission(sp.getSelfType(),
1625                                                         sb.toString(),
1626                                                         sp.getSelfActions(),
1627                                                         sp.getCerts()));
1628             } else {
1629                 try {
1630                     // we found an instantiated permission.
1631                     // use its class loader to instantiate a new permission.
1632                     Constructor<?> c;
1633                     // name parameter can not be null
1634                     if (sp.getSelfActions() == null) {
1635                         try {
1636                             c = pc.getConstructor(PARAMS1);
1637                             perms.add((Permission)c.newInstance
1638                                  (new Object[] {sb.toString()}));
1639                         } catch (NoSuchMethodException ne) {
1640                             c = pc.getConstructor(PARAMS2);
1641                             perms.add((Permission)c.newInstance
1642                                  (new Object[] {sb.toString(),
1643                                                 sp.getSelfActions() }));
1644                         }
1645                     } else {
1646                         c = pc.getConstructor(PARAMS2);
1647                         perms.add((Permission)c.newInstance
1648                            (new Object[] {sb.toString(),
1649                                           sp.getSelfActions()}));
1650                     }
1651                 } catch (Exception nme) {
1652                     if (debug != null) {
1653                         debug.println("self entry expansion " +
1654                         " instantiation failed: "
1655                         +  nme.toString());
1656                     }
1657                 }
1658             }
1659         } catch (Exception e) {
1660             if (debug != null) {
1661                 debug.println(e.toString());
1662             }
1663         }
1664     }
1665 
1666     /**
1667      * return the principal class/name pair in the 2D array.
1668      * array[x][y]:     x corresponds to the array length.
1669      *                  if (y == 0), it's the principal class.
1670      *                  if (y == 1), it's the principal name.
1671      */
1672     private String[][] getPrincipalInfo
1673         (PolicyParser.PrincipalEntry pe, Principal[] pdp) {
1674 
1675         // there are 3 possibilities:
1676         // 1) the entry's Principal class and name are not wildcarded
1677         // 2) the entry's Principal name is wildcarded only
1678         // 3) the entry's Principal class and name are wildcarded
1679 
1680         if (!pe.principalClass.equals
1681             (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
1682             !pe.principalName.equals
1683             (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
1684 
1685             // build an info array for the principal
1686             // from the Policy entry
1687             String[][] info = new String[1][2];
1688             info[0][0] = pe.principalClass;
1689             info[0][1] = pe.principalName;
1690             return info;
1691 
1692         } else if (!pe.principalClass.equals
1693                    (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
1694                    pe.principalName.equals
1695                    (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
1696 
1697             // build an info array for every principal
1698             // in the current domain which has a principal class
1699             // that is equal to policy entry principal class name
1700             List<Principal> plist = new ArrayList<>();
1701             for (int i = 0; i < pdp.length; i++) {
1702                 if(pe.principalClass.equals(pdp[i].getClass().getName()))
1703                     plist.add(pdp[i]);
1704             }
1705             String[][] info = new String[plist.size()][2];
1706             int i = 0;
1707             java.util.Iterator<Principal> pIterator = plist.iterator();
1708             while (pIterator.hasNext()) {
1709                 Principal p = pIterator.next();
1710                 info[i][0] = p.getClass().getName();
1711                 info[i][1] = p.getName();
1712                 i++;
1713             }
1714             return info;
1715 
1716         } else {
1717 
1718             // build an info array for every
1719             // one of the current Domain's principals
1720 
1721             String[][] info = new String[pdp.length][2];
1722 
1723             for (int i = 0; i < pdp.length; i++) {
1724                 info[i][0] = pdp[i].getClass().getName();
1725                 info[i][1] = pdp[i].getName();
1726             }
1727             return info;
1728         }
1729     }
1730 
1731     /*
1732      * Returns the signer certificates from the list of certificates
1733      * associated with the given code source.
1734      *
1735      * The signer certificates are those certificates that were used
1736      * to verifysigned code originating from the codesource location.
1737      *
1738      * This method assumes that in the given code source, each signer
1739      * certificate is followed by its supporting certificate chain
1740      * (which may be empty), and that the signer certificate and its
1741      * supporting certificate chain are ordered bottom-to-top
1742      * (i.e., with the signer certificate first and the (root) certificate
1743      * authority last).
1744      */
1745     protected Certificate[] getSignerCertificates(CodeSource cs) {
1746         Certificate[] certs = null;
1747         if ((certs = cs.getCertificates()) == null)
1748             return null;
1749         for (int i=0; i<certs.length; i++) {
1750             if (!(certs[i] instanceof X509Certificate))
1751                 return cs.getCertificates();
1752         }
1753 
1754         // Do we have to do anything?
1755         int i = 0;
1756         int count = 0;
1757         while (i < certs.length) {
1758             count++;
1759             while (((i+1) < certs.length)
1760                    && ((X509Certificate)certs[i]).getIssuerDN().equals(
1761                            ((X509Certificate)certs[i+1]).getSubjectDN())) {
1762                 i++;
1763             }
1764             i++;
1765         }
1766         if (count == certs.length)
1767             // Done
1768             return certs;
1769 
1770         ArrayList<Certificate> userCertList = new ArrayList<>();
1771         i = 0;
1772         while (i < certs.length) {
1773             userCertList.add(certs[i]);
1774             while (((i+1) < certs.length)
1775                    && ((X509Certificate)certs[i]).getIssuerDN().equals(
1776                            ((X509Certificate)certs[i+1]).getSubjectDN())) {
1777                 i++;
1778             }
1779             i++;
1780         }
1781         Certificate[] userCerts = new Certificate[userCertList.size()];
1782         userCertList.toArray(userCerts);
1783         return userCerts;
1784     }
1785 
1786     private CodeSource canonicalizeCodebase(CodeSource cs,
1787                                             boolean extractSignerCerts) {
1788 
1789         String path = null;
1790 
1791         CodeSource canonCs = cs;
1792         URL u = cs.getLocation();
1793         if (u != null) {
1794             if (u.getProtocol().equals("jar")) {
1795                 // unwrap url embedded inside jar url
1796                 String spec = u.getFile();
1797                 int separator = spec.indexOf("!/");
1798                 if (separator != -1) {
1799                     try {
1800                         u = new URL(spec.substring(0, separator));
1801                     } catch (MalformedURLException e) {
1802                         // Fail silently. In this case, url stays what
1803                         // it was above
1804                     }
1805                 }
1806             }
1807             if (u.getProtocol().equals("file")) {
1808                 boolean isLocalFile = false;
1809                 String host = u.getHost();
1810                 isLocalFile = (host == null || host.equals("") ||
1811                     host.equals("~") || host.equalsIgnoreCase("localhost"));
1812 
1813                 if (isLocalFile) {
1814                     path = u.getFile().replace('/', File.separatorChar);
1815                     path = ParseUtil.decode(path);
1816                 }
1817             }
1818         }
1819 
1820         if (path != null) {
1821             try {
1822                 URL csUrl = null;
1823                 path = canonPath(path);
1824                 csUrl = ParseUtil.fileToEncodedURL(new File(path));
1825 
1826                 if (extractSignerCerts) {
1827                     canonCs = new CodeSource(csUrl,
1828                                              getSignerCertificates(cs));
1829                 } else {
1830                     canonCs = new CodeSource(csUrl,
1831                                              cs.getCertificates());
1832                 }
1833             } catch (IOException ioe) {
1834                 // leave codesource as it is, unless we have to extract its
1835                 // signer certificates
1836                 if (extractSignerCerts) {
1837                     canonCs = new CodeSource(cs.getLocation(),
1838                                              getSignerCertificates(cs));
1839                 }
1840             }
1841         } else {
1842             if (extractSignerCerts) {
1843                 canonCs = new CodeSource(cs.getLocation(),
1844                                          getSignerCertificates(cs));
1845             }
1846         }
1847         return canonCs;
1848     }
1849 
1850     // Wrapper to return a canonical path that avoids calling getCanonicalPath()
1851     // with paths that are intended to match all entries in the directory
1852     private static String canonPath(String path) throws IOException {
1853         if (path.endsWith("*")) {
1854             path = path.substring(0, path.length()-1) + "-";
1855             path = new File(path).getCanonicalPath();
1856             return path.substring(0, path.length()-1) + "*";
1857         } else {
1858             return new File(path).getCanonicalPath();
1859         }
1860     }
1861 
1862     private String printPD(ProtectionDomain pd) {
1863         Principal[] principals = pd.getPrincipals();
1864         String pals = "<no principals>";
1865         if (principals != null && principals.length > 0) {
1866             StringBuilder palBuf = new StringBuilder("(principals ");
1867             for (int i = 0; i < principals.length; i++) {
1868                 palBuf.append(principals[i].getClass().getName() +
1869                               " \"" + principals[i].getName() +
1870                               "\"");
1871                 if (i < principals.length-1)
1872                     palBuf.append(", ");
1873                 else
1874                     palBuf.append(")");
1875             }
1876             pals = palBuf.toString();
1877         }
1878         return "PD CodeSource: "
1879                 + pd.getCodeSource()
1880                 +"\n\t" + "PD ClassLoader: "
1881                 + pd.getClassLoader()
1882                 +"\n\t" + "PD Principals: "
1883                 + pals;
1884     }
1885 
1886     /**
1887      * return true if no replacement was performed,
1888      * or if replacement succeeded.
1889      */
1890     private boolean replacePrincipals(
1891         List<PolicyParser.PrincipalEntry> principals, KeyStore keystore) {
1892 
1893         if (principals == null || principals.size() == 0 || keystore == null)
1894             return true;
1895 
1896         ListIterator<PolicyParser.PrincipalEntry> i = principals.listIterator();
1897         while (i.hasNext()) {
1898             PolicyParser.PrincipalEntry pppe = i.next();
1899             if (pppe.principalClass.equals(PolicyParser.REPLACE_NAME)) {
1900 
1901                 // perform replacement
1902                 // (only X509 replacement is possible now)
1903                 String name;
1904                 if ((name = getDN(pppe.principalName, keystore)) == null) {
1905                     return false;
1906                 }
1907 
1908                 if (debug != null) {
1909                     debug.println("  Replacing \"" +
1910                         pppe.principalName +
1911                         "\" with " +
1912                         X500PRINCIPAL + "/\"" +
1913                         name +
1914                         "\"");
1915                 }
1916 
1917                 pppe.principalClass = X500PRINCIPAL;
1918                 pppe.principalName = name;
1919             }
1920         }
1921         // return true if no replacement was performed,
1922         // or if replacement succeeded
1923         return true;
1924     }
1925 
1926     private void expandPermissionName(PolicyParser.PermissionEntry pe,
1927                                         KeyStore keystore) throws Exception {
1928         // short cut the common case
1929         if (pe.name == null || pe.name.indexOf("${{", 0) == -1) {
1930             return;
1931         }
1932 
1933         int startIndex = 0;
1934         int b, e;
1935         StringBuilder sb = new StringBuilder();
1936         while ((b = pe.name.indexOf("${{", startIndex)) != -1) {
1937             e = pe.name.indexOf("}}", b);
1938             if (e < 1) {
1939                 break;
1940             }
1941             sb.append(pe.name.substring(startIndex, b));
1942 
1943             // get the value in ${{...}}
1944             String value = pe.name.substring(b+3, e);
1945 
1946             // parse up to the first ':'
1947             int colonIndex;
1948             String prefix = value;
1949             String suffix;
1950             if ((colonIndex = value.indexOf(":")) != -1) {
1951                 prefix = value.substring(0, colonIndex);
1952             }
1953 
1954             // handle different prefix possibilities
1955             if (prefix.equalsIgnoreCase("self")) {
1956                 // do nothing - handled later
1957                 sb.append(pe.name.substring(b, e+2));
1958                 startIndex = e+2;
1959                 continue;
1960             } else if (prefix.equalsIgnoreCase("alias")) {
1961                 // get the suffix and perform keystore alias replacement
1962                 if (colonIndex == -1) {
1963                     MessageFormat form = new MessageFormat
1964                         (ResourcesMgr.getString
1965                         ("alias.name.not.provided.pe.name."));
1966                     Object[] source = {pe.name};
1967                     throw new Exception(form.format(source));
1968                 }
1969                 suffix = value.substring(colonIndex+1);
1970                 if ((suffix = getDN(suffix, keystore)) == null) {
1971                     MessageFormat form = new MessageFormat
1972                         (ResourcesMgr.getString
1973                         ("unable.to.perform.substitution.on.alias.suffix"));
1974                     Object[] source = {value.substring(colonIndex+1)};
1975                     throw new Exception(form.format(source));
1976                 }
1977 
1978                 sb.append(X500PRINCIPAL + " \"" + suffix + "\"");
1979                 startIndex = e+2;
1980             } else {
1981                 MessageFormat form = new MessageFormat
1982                         (ResourcesMgr.getString
1983                         ("substitution.value.prefix.unsupported"));
1984                 Object[] source = {prefix};
1985                 throw new Exception(form.format(source));
1986             }
1987         }
1988 
1989         // copy the rest of the value
1990         sb.append(pe.name.substring(startIndex));
1991 
1992         // replace the name with expanded value
1993         if (debug != null) {
1994             debug.println("  Permission name expanded from:\n\t" +
1995                         pe.name + "\nto\n\t" + sb.toString());
1996         }
1997         pe.name = sb.toString();
1998     }
1999 
2000     private String getDN(String alias, KeyStore keystore) {
2001         Certificate cert = null;
2002         try {
2003             cert = keystore.getCertificate(alias);
2004         } catch (Exception e) {
2005             if (debug != null) {
2006                 debug.println("  Error retrieving certificate for '" +
2007                                 alias +
2008                                 "': " +
2009                                 e.toString());
2010             }
2011             return null;
2012         }
2013 
2014         if (cert == null || !(cert instanceof X509Certificate)) {
2015             if (debug != null) {
2016                 debug.println("  -- No certificate for '" +
2017                                 alias +
2018                                 "' - ignoring entry");
2019             }
2020             return null;
2021         } else {
2022             X509Certificate x509Cert = (X509Certificate)cert;
2023 
2024             // 4702543:  X500 names with an EmailAddress
2025             // were encoded incorrectly.  create new
2026             // X500Principal name with correct encoding
2027 
2028             X500Principal p = new X500Principal
2029                 (x509Cert.getSubjectX500Principal().toString());
2030             return p.getName();
2031         }
2032     }
2033 
2034     /**
2035      * Checks public key. If it is marked as trusted in
2036      * the identity database, add it to the policy
2037      * with the AllPermission.
2038      */
2039     private boolean checkForTrustedIdentity(final Certificate cert,
2040         PolicyInfo myInfo)
2041     {
2042         return false;
2043     }
2044 
2045     /**
2046      * Each entry in the policy configuration file is represented by a
2047      * PolicyEntry object.  <p>
2048      *
2049      * A PolicyEntry is a (CodeSource,Permission) pair.  The
2050      * CodeSource contains the (URL, PublicKey) that together identify
2051      * where the Java bytecodes come from and who (if anyone) signed
2052      * them.  The URL could refer to localhost.  The URL could also be
2053      * null, meaning that this policy entry is given to all comers, as
2054      * long as they match the signer field.  The signer could be null,
2055      * meaning the code is not signed. <p>
2056      *
2057      * The Permission contains the (Type, Name, Action) triplet. <p>
2058      *
2059      * For now, the Policy object retrieves the public key from the
2060      * X.509 certificate on disk that corresponds to the signedBy
2061      * alias specified in the Policy config file.  For reasons of
2062      * efficiency, the Policy object keeps a hashtable of certs already
2063      * read in.  This could be replaced by a secure internal key
2064      * store.
2065      *
2066      * <p>
2067      * For example, the entry
2068      * <pre>
2069      *          permission java.io.File "/tmp", "read,write",
2070      *          signedBy "Duke";
2071      * </pre>
2072      * is represented internally
2073      * <pre>
2074      *
2075      * FilePermission f = new FilePermission("/tmp", "read,write");
2076      * PublicKey p = publickeys.get("Duke");
2077      * URL u = InetAddress.getLocalHost();
2078      * CodeBase c = new CodeBase( p, u );
2079      * pe = new PolicyEntry(f, c);
2080      * </pre>
2081      *
2082      * @author Marianne Mueller
2083      * @author Roland Schemers
2084      * @see java.security.CodeSource
2085      * @see java.security.Policy
2086      * @see java.security.Permissions
2087      * @see java.security.ProtectionDomain
2088      */
2089     private static class PolicyEntry {
2090 
2091         private final CodeSource codesource;
2092         final List<Permission> permissions;
2093         private final List<PolicyParser.PrincipalEntry> principals;
2094 
2095         /**
2096          * Given a Permission and a CodeSource, create a policy entry.
2097          *
2098          * XXX Decide if/how to add validity fields and "purpose" fields to
2099          * XXX policy entries
2100          *
2101          * @param cs the CodeSource, which encapsulates the URL and the
2102          *        public key
2103          *        attributes from the policy config file. Validity checks
2104          *        are performed on the public key before PolicyEntry is
2105          *        called.
2106          *
2107          */
2108         PolicyEntry(CodeSource cs, List<PolicyParser.PrincipalEntry> principals)
2109         {
2110             this.codesource = cs;
2111             this.permissions = new ArrayList<Permission>();
2112             this.principals = principals; // can be null
2113         }
2114 
2115         PolicyEntry(CodeSource cs)
2116         {
2117             this(cs, null);
2118         }
2119 
2120         List<PolicyParser.PrincipalEntry> getPrincipals() {
2121             return principals; // can be null
2122         }
2123 
2124         /**
2125          * add a Permission object to this entry.
2126          * No need to sync add op because perms are added to entry only
2127          * while entry is being initialized
2128          */
2129         void add(Permission p) {
2130             permissions.add(p);
2131         }
2132 
2133         /**
2134          * Return the CodeSource for this policy entry
2135          */
2136         CodeSource getCodeSource() {
2137             return codesource;
2138         }
2139 
2140         @Override public String toString(){
2141             StringBuilder sb = new StringBuilder();
2142             sb.append(ResourcesMgr.getString("LPARAM"));
2143             sb.append(getCodeSource());
2144             sb.append("\n");
2145             for (int j = 0; j < permissions.size(); j++) {
2146                 Permission p = permissions.get(j);
2147                 sb.append(ResourcesMgr.getString("SPACE"));
2148                 sb.append(ResourcesMgr.getString("SPACE"));
2149                 sb.append(p);
2150                 sb.append(ResourcesMgr.getString("NEWLINE"));
2151             }
2152             sb.append(ResourcesMgr.getString("RPARAM"));
2153             sb.append(ResourcesMgr.getString("NEWLINE"));
2154             return sb.toString();
2155         }
2156     }
2157 
2158     private static class SelfPermission extends Permission {
2159 
2160         private static final long serialVersionUID = -8315562579967246806L;
2161 
2162         /**
2163          * The class name of the Permission class that will be
2164          * created when this self permission is expanded .
2165          *
2166          * @serial
2167          */
2168         private String type;
2169 
2170         /**
2171          * The permission name.
2172          *
2173          * @serial
2174          */
2175         private String name;
2176 
2177         /**
2178          * The actions of the permission.
2179          *
2180          * @serial
2181          */
2182         private String actions;
2183 
2184         /**
2185          * The certs of the permission.
2186          *
2187          * @serial
2188          */
2189         private Certificate certs[];
2190 
2191         /**
2192          * Creates a new SelfPermission containing the permission
2193          * information needed later to expand the self
2194          * @param type the class name of the Permission class that will be
2195          * created when this permission is expanded and if necessary resolved.
2196          * @param name the name of the permission.
2197          * @param actions the actions of the permission.
2198          * @param certs the certificates the permission's class was signed with.
2199          * This is a list of certificate chains, where each chain is composed of
2200          * a signer certificate and optionally its supporting certificate chain.
2201          * Each chain is ordered bottom-to-top (i.e., with the signer
2202          * certificate first and the (root) certificate authority last).
2203          */
2204         public SelfPermission(String type, String name, String actions,
2205                               Certificate certs[])
2206         {
2207             super(type);
2208             if (type == null) {
2209                 throw new NullPointerException
2210                     (ResourcesMgr.getString("type.can.t.be.null"));
2211             }
2212             this.type = type;
2213             this.name = name;
2214             this.actions = actions;
2215             if (certs != null) {
2216                 // Extract the signer certs from the list of certificates.
2217                 for (int i=0; i<certs.length; i++) {
2218                     if (!(certs[i] instanceof X509Certificate)) {
2219                         // there is no concept of signer certs, so we store the
2220                         // entire cert array
2221                         this.certs = certs.clone();
2222                         break;
2223                     }
2224                 }
2225 
2226                 if (this.certs == null) {
2227                     // Go through the list of certs and see if all the certs are
2228                     // signer certs.
2229                     int i = 0;
2230                     int count = 0;
2231                     while (i < certs.length) {
2232                         count++;
2233                         while (((i+1) < certs.length) &&
2234                             ((X509Certificate)certs[i]).getIssuerDN().equals(
2235                             ((X509Certificate)certs[i+1]).getSubjectDN())) {
2236                             i++;
2237                         }
2238                         i++;
2239                     }
2240                     if (count == certs.length) {
2241                         // All the certs are signer certs, so we store the
2242                         // entire array
2243                         this.certs = certs.clone();
2244                     }
2245 
2246                     if (this.certs == null) {
2247                         // extract the signer certs
2248                         ArrayList<Certificate> signerCerts =
2249                             new ArrayList<>();
2250                         i = 0;
2251                         while (i < certs.length) {
2252                             signerCerts.add(certs[i]);
2253                             while (((i+1) < certs.length) &&
2254                                 ((X509Certificate)certs[i]).getIssuerDN().equals(
2255                                 ((X509Certificate)certs[i+1]).getSubjectDN())) {
2256                                 i++;
2257                             }
2258                             i++;
2259                         }
2260                         this.certs = new Certificate[signerCerts.size()];
2261                         signerCerts.toArray(this.certs);
2262                     }
2263                 }
2264             }
2265         }
2266 
2267         /**
2268          * This method always returns false for SelfPermission permissions.
2269          * That is, an SelfPermission never considered to
2270          * imply another permission.
2271          *
2272          * @param p the permission to check against.
2273          *
2274          * @return false.
2275          */
2276         @Override public boolean implies(Permission p) {
2277             return false;
2278         }
2279 
2280         /**
2281          * Checks two SelfPermission objects for equality.
2282          *
2283          * Checks that <i>obj</i> is an SelfPermission, and has
2284          * the same type (class) name, permission name, actions, and
2285          * certificates as this object.
2286          *
2287          * @param obj the object we are testing for equality with this object.
2288          *
2289          * @return true if obj is an SelfPermission, and has the same
2290          * type (class) name, permission name, actions, and
2291          * certificates as this object.
2292          */
2293         @Override public boolean equals(Object obj) {
2294             if (obj == this)
2295                 return true;
2296 
2297             if (! (obj instanceof SelfPermission))
2298                 return false;
2299             SelfPermission that = (SelfPermission) obj;
2300 
2301             if (!(this.type.equals(that.type) &&
2302                 this.name.equals(that.name) &&
2303                 this.actions.equals(that.actions)))
2304                 return false;
2305 
2306             if (this.certs.length != that.certs.length)
2307                 return false;
2308 
2309             int i,j;
2310             boolean match;
2311 
2312             for (i = 0; i < this.certs.length; i++) {
2313                 match = false;
2314                 for (j = 0; j < that.certs.length; j++) {
2315                     if (this.certs[i].equals(that.certs[j])) {
2316                         match = true;
2317                         break;
2318                     }
2319                 }
2320                 if (!match) return false;
2321             }
2322 
2323             for (i = 0; i < that.certs.length; i++) {
2324                 match = false;
2325                 for (j = 0; j < this.certs.length; j++) {
2326                     if (that.certs[i].equals(this.certs[j])) {
2327                         match = true;
2328                         break;
2329                     }
2330                 }
2331                 if (!match) return false;
2332             }
2333             return true;
2334         }
2335 
2336         /**
2337          * Returns the hash code value for this object.
2338          *
2339          * @return a hash code value for this object.
2340          */
2341         @Override public int hashCode() {
2342             int hash = type.hashCode();
2343             if (name != null)
2344                 hash ^= name.hashCode();
2345             if (actions != null)
2346                 hash ^= actions.hashCode();
2347             return hash;
2348         }
2349 
2350         /**
2351          * Returns the canonical string representation of the actions,
2352          * which currently is the empty string "", since there are no actions
2353          * for an SelfPermission. That is, the actions for the
2354          * permission that will be created when this SelfPermission
2355          * is resolved may be non-null, but an SelfPermission
2356          * itself is never considered to have any actions.
2357          *
2358          * @return the empty string "".
2359          */
2360         @Override public String getActions() {
2361             return "";
2362         }
2363 
2364         public String getSelfType() {
2365             return type;
2366         }
2367 
2368         public String getSelfName() {
2369             return name;
2370         }
2371 
2372         public String getSelfActions() {
2373             return actions;
2374         }
2375 
2376         public Certificate[] getCerts() {
2377             return certs;
2378         }
2379 
2380         /**
2381          * Returns a string describing this SelfPermission.  The convention
2382          * is to specify the class name, the permission name, and the actions,
2383          * in the following format: '(unresolved "ClassName" "name" "actions")'.
2384          *
2385          * @return information about this SelfPermission.
2386          */
2387         @Override public String toString() {
2388             return "(SelfPermission " + type + " " + name + " " + actions + ")";
2389         }
2390     }
2391 
2392     /**
2393      * holds policy information that we need to synch on
2394      */
2395     private static class PolicyInfo {
2396         private static final boolean verbose = false;
2397 
2398         // Stores grant entries in the policy
2399         final List<PolicyEntry> policyEntries;
2400 
2401         // Stores grant entries gotten from identity database
2402         // Use separate lists to avoid sync on policyEntries
2403         final List<PolicyEntry> identityPolicyEntries;
2404 
2405         // Maps aliases to certs
2406         final Map aliasMapping;
2407 
2408         // Maps ProtectionDomain to PermissionCollection
2409         private final ProtectionDomainCache[] pdMapping;
2410         private java.util.Random random;
2411 
2412         PolicyInfo(int numCaches) {
2413             policyEntries = new ArrayList<PolicyEntry>();
2414             identityPolicyEntries =
2415                 Collections.synchronizedList(new ArrayList<PolicyEntry>(2));
2416             aliasMapping = Collections.synchronizedMap(new HashMap(11));
2417 
2418             pdMapping = new ProtectionDomainCache[numCaches];
2419             JavaSecurityProtectionDomainAccess jspda
2420                 = SharedSecrets.getJavaSecurityProtectionDomainAccess();
2421             for (int i = 0; i < numCaches; i++) {
2422                 pdMapping[i] = jspda.getProtectionDomainCache();
2423             }
2424             if (numCaches > 1) {
2425                 random = new java.util.Random();
2426             }
2427         }
2428         ProtectionDomainCache getPdMapping() {
2429             if (pdMapping.length == 1) {
2430                 return pdMapping[0];
2431             } else {
2432                 int i = java.lang.Math.abs(random.nextInt() % pdMapping.length);
2433                 return pdMapping[i];
2434             }
2435         }
2436     }
2437 }